package opgave2;

public class Lijst<E extends Data> implements LijstInterface<E> {

	Knoop<E> first, current, last;
	private int numberOfElements;
	
	public Lijst() {
		first = null;
		current = null;
		last = null;
		numberOfElements = 0;
	}
	
	public boolean isEmpty() {
		return size() == 0;
	}

	public Lijst<E> init() {
		first = null;
		current = null;
		last = null;
		numberOfElements = 0;
		return this;
	}

	public int size() {
		return numberOfElements;
	}

	public Lijst<E> insert(E d) {
		// Het meegegeven object d wordt in de Knoop-class gecloned dus hoeft hier niet gedaan te worden.
		Knoop<E> knoop = new Knoop<E>(d);
		//Als het de eerste is dan knoop zonder referenties
		if(isEmpty()){
			first = knoop;
			current = knoop;
			last = knoop;
			numberOfElements += 1;
			return this;
		}
		//andere gevallen
		numberOfElements += 1;
		//loop alles door, op het moment dat compareto >0 retourneert, voor de current invoegen
		for (boolean inList = setFirst(); inList; inList = getNext()) {
		    if(current.data.compareTo(d) > 0) {
		    	knoop.prior = current.prior;
		    	if(knoop.prior != null) {
		    		knoop.prior.next = knoop;
		    	} else {
		    		first = knoop;
		    	}
		    	
		    	knoop.next = current;
		    	knoop.next.prior = knoop;
		    	current = knoop;
		    	return this;
		    }
		}
		//als alles doorgelopen is, achter de last(nu current) plaatsen
		last.next = knoop;
		knoop.prior = last;
		last = knoop;
		current = knoop;
		return this;
	}

	public E retrieve() {
		return current.data == null ? null : (E) current.data.clone();
	}

	public Lijst<E> remove() {
		if(size() == 1){
			return init();
		}
		if(current == last){
			current = current.prior;
			last = current;
			last.next = null;
		} else if(current == first){
			current = first.next;
			current.prior = null;
			first = current;
		} else {
			current.prior.next = current.next;
			current.next.prior = current.prior;
			current = current.next;
		}
		
		numberOfElements -= 1;
		return this;
	}

	public boolean find(E d) {
		for (boolean inList = setFirst(); inList; inList = getNext()) {
		    if(current.data.compareTo(d) == 0) {
		    	return true;
		    } else if(current.data.compareTo(d) > 0) {
		    	if (current != first) {
			    	current = current.prior;	
		    	}
		    	return false;
		    }
		}
		return false;
	}

	public boolean setFirst() {
		if (!isEmpty()) {
			current = first;
			return true;
		}
		return false;
	}

	public boolean setLast() {
		if (!isEmpty()) {
			current = last;
			return true;
		}
		return false;
	}

	public boolean getNext() {
		if (!isEmpty() && current != last) {
			current = current.next;
			return true;
		}
		return false;
	}

	public boolean getPrior() {
		if (!isEmpty() && current != first) {
			current = current.prior;
			return true;
		}
		return false;
	}
	
	public Lijst<E> clone() {
		
		Lijst<E> result = new Lijst<E>();

		Knoop<E> backupCurrent = current;
		
		for (boolean inList = setLast(); inList; inList = getPrior()) {
			result.insert(retrieve());
		}
		
		current = backupCurrent;
		if(!isEmpty()) {
			result.find(retrieve());
		}
		
		return result;
	}
}
